package com.kaifamiao.annotation.type;

import org.apache.ibatis.type.JdbcType;
import org.apache.ibatis.type.TypeHandler;

import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.time.LocalDate;
import java.util.logging.Logger;

/**
 * 自定义 TypeHandler 类，用来处理 LocalDate 类型的对象
 */
public class LocalDateTypeHandler implements TypeHandler<LocalDate> {

    private Logger logger = Logger.getAnonymousLogger();

    @Override
    public void setParameter( PreparedStatement ps , int index , LocalDate localDate, JdbcType jdbcType )
            throws SQLException {
        logger.info( "为 PreparedStatement 设置第 " + index + " 个参数值: " + localDate );
        logger.info( String.valueOf( jdbcType ) );
        java.sql.Date date = null ;
        if( localDate != null ) {
            // 类型转换: 根据 localDate 创建并返回新的 java.sql.Date 实例
            date = java.sql.Date.valueOf( localDate ); // Java 8 为 java.sql.Date 新增的 类方法
        }
        // 为 PreparedStatement 设置参数值
        ps.setDate( index , date );
    }

    /**
     * 根据列名或列别名从结果集中获取指定列的值
     * @param rs 表示已经定位的结果集(已经确定到具体某行数据)
     * @param label 表示查询语句中的 列名 或 别名
     * @return 返回与指定列对应的 LocalDate 实例
     * @throws SQLException
     */
    @Override
    public LocalDate getResult( ResultSet rs , String label ) throws SQLException {
        logger.info( "根据列名或列别名获取指定列的值" );
        LocalDate localDate = null ;
        // 从结果集中以 java.sql.Date 类型获取 label 对应的列的值
        java.sql.Date date = rs.getDate( label );
        if( date != null ) {
            localDate = date.toLocalDate(); // Java 8 中为 java.sql.Date 新增的实例方法
        }
        return localDate;
    }

    /**
     * 根据列的索引从结果集中获取指定列的值
     * @param rs 表示已经定位的结果集(已经确定到具体某行数据)
     * @param index 表示将要获取取值的列的索引(即查询结果中该列的索引)
     * @return 返回与指定列对应的 LocalDate 实例
     * @throws SQLException
     */
    @Override
    public LocalDate getResult( ResultSet rs , int index ) throws SQLException {
        logger.info( "根据列的索引获取指定列的值" );
        LocalDate localDate = null ;
        // 从结果集中以 java.sql.Date 类型获取 index 对应的列的值
        java.sql.Date date = rs.getDate( index );
        if( date != null ) {
            localDate = date.toLocalDate(); // Java 8 中为 java.sql.Date 新增的实例方法
        }
        return localDate;
    }

    /**
     * 如果调用的是存储过程或数据库函数，则可以根据传出参数的索引获取存储过程或函数的传出结果
     * @param cs 用于执行 存储过程 或 数据库函数 的 CallableStatement 对象
     * @param index 表示传出参数的索引值
     * @return 返回与指定传出参数对应的 LocalDate 实例
     * @throws SQLException
     */
    @Override
    public LocalDate getResult( CallableStatement cs , int index ) throws SQLException {
        logger.info( "获取指定传出参数的值" );
        LocalDate localDate = null ;
        // 用 CallableStatement 来获取指定传出参数传出的值
        java.sql.Date date = cs.getDate( index );
        if( date != null ) {
            localDate = date.toLocalDate(); // Java 8 中为 java.sql.Date 新增的实例方法
        }
        return localDate;
    }
}
